使用 ruamel.yaml 时如何防止重新格式化 yaml 文件?
How can I prevent re-formating of a yaml file when ruamel.yaml is used?
我在 How to auto-dump modified values in nested dictionaries using ruamel.yaml 的相关答案中使用解决方案
.
我观察到当 self.update(self.yaml.load(f) or {})
被调用时:它会根据字母顺序对 yaml
文件进行排序,并将其缩进更改为 2,从而不断重新格式化 yaml
文件。
=> 是否可以防止重新格式化?
我也试过下面一行,为了保持缩进为 4 space:
yaml = YAML(typ="safe")
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.default_flow_style = False
config.yaml:
c: # my comment
b:
f: 5
e: 22
a:
z: 4
b: 4 # my comment
代码(与 How to auto-dump modified values in nested dictionaries using ruamel.yaml 完全相同的代码
):
#!/usr/bin/env python3
import sys
import os
from pathlib import Path
import ruamel.yaml
class SubConfig(dict):
def __init__(self, parent):
self.parent = parent
def updated(self):
self.parent.updated()
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
return res
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
return
_SR = ruamel.yaml.representer.SafeRepresenter
_SR.add_representer(SubConfig, _SR.represent_dict)
class Config(dict):
def __init__(self, filename, auto_dump=True):
self.filename = filename if hasattr(filename, "open") else Path(filename)
self.auto_dump = auto_dump
self.changed = False
self.yaml = ruamel.yaml.YAML(typ="safe")
self.yaml.default_flow_style = False
if self.filename.exists():
with open(filename) as f:
self.update(self.yaml.load(f) or {})
def updated(self):
if self.auto_dump:
self.dump(force=True)
else:
self.changed = True
def dump(self, force=False):
if not self.changed and not force:
return
with open(self.filename, "w") as f:
self.yaml.dump(dict(self), f)
self.changed = False
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
cfg = Config(Path("config.yaml"))
=> config.yaml
文件更新如下,其中,其排序和缩进变为 2,并删除注释:
a:
b: 4
z: 4
c:
b:
e: 5
f: 22
无法阻止缩进“重新格式化”。 ruamel.yaml
记录为
规范化格式,以便所有(块样式)映射缩进相同,
并且所有(块样式)序列都缩进相同。但是,您可以设置其中的每一个,您似乎没有为映射做这些
(YAML 中 Python dict
s 的表示):
import sys
import ruamel.yaml
data = dict(a=dict(b=[42, 18]))
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=4, offset=2)
yaml.dump(data, sys.stdout)
这为映射和序列提供了四个缩进:
a:
b:
- 42
- 18
确保使用默认值(往返)loader/dumper 以防止排序并让您完全控制缩进输出。
我在 How to auto-dump modified values in nested dictionaries using ruamel.yaml 的相关答案中使用解决方案 .
我观察到当 self.update(self.yaml.load(f) or {})
被调用时:它会根据字母顺序对 yaml
文件进行排序,并将其缩进更改为 2,从而不断重新格式化 yaml
文件。
=> 是否可以防止重新格式化?
我也试过下面一行,为了保持缩进为 4 space:
yaml = YAML(typ="safe")
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.default_flow_style = False
config.yaml:
c: # my comment
b:
f: 5
e: 22
a:
z: 4
b: 4 # my comment
代码(与 How to auto-dump modified values in nested dictionaries using ruamel.yaml 完全相同的代码 ):
#!/usr/bin/env python3
import sys
import os
from pathlib import Path
import ruamel.yaml
class SubConfig(dict):
def __init__(self, parent):
self.parent = parent
def updated(self):
self.parent.updated()
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
return res
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
return
_SR = ruamel.yaml.representer.SafeRepresenter
_SR.add_representer(SubConfig, _SR.represent_dict)
class Config(dict):
def __init__(self, filename, auto_dump=True):
self.filename = filename if hasattr(filename, "open") else Path(filename)
self.auto_dump = auto_dump
self.changed = False
self.yaml = ruamel.yaml.YAML(typ="safe")
self.yaml.default_flow_style = False
if self.filename.exists():
with open(filename) as f:
self.update(self.yaml.load(f) or {})
def updated(self):
if self.auto_dump:
self.dump(force=True)
else:
self.changed = True
def dump(self, force=False):
if not self.changed and not force:
return
with open(self.filename, "w") as f:
self.yaml.dump(dict(self), f)
self.changed = False
def __setitem__(self, key, value):
if isinstance(value, dict):
v = SubConfig(self)
v.update(value)
value = v
super().__setitem__(key, value)
self.updated()
def __getitem__(self, key):
try:
res = super().__getitem__(key)
except KeyError:
super().__setitem__(key, SubConfig(self))
self.updated()
return super().__getitem__(key)
def __delitem__(self, key):
res = super().__delitem__(key)
self.updated()
def update(self, *args, **kw):
for arg in args:
for k, v in arg.items():
self[k] = v
for k, v in kw.items():
self[k] = v
self.updated()
cfg = Config(Path("config.yaml"))
=> config.yaml
文件更新如下,其中,其排序和缩进变为 2,并删除注释:
a:
b: 4
z: 4
c:
b:
e: 5
f: 22
无法阻止缩进“重新格式化”。 ruamel.yaml
记录为
规范化格式,以便所有(块样式)映射缩进相同,
并且所有(块样式)序列都缩进相同。但是,您可以设置其中的每一个,您似乎没有为映射做这些
(YAML 中 Python dict
s 的表示):
import sys
import ruamel.yaml
data = dict(a=dict(b=[42, 18]))
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=4, offset=2)
yaml.dump(data, sys.stdout)
这为映射和序列提供了四个缩进:
a:
b:
- 42
- 18
确保使用默认值(往返)loader/dumper 以防止排序并让您完全控制缩进输出。